To add a new kernel-level device driver, you must create your own system file. This file should contain the appropriate directive that tells lboot how to include your driver, and it should specify which memory space will be allocated by your device. The filename must include the .sm suffix and reside in the directory /var/sysgen/system. Because lboot can probe for EISA devices, it can conditionally include an EISA device driver into the kernel.
Synopsis
VECTOR: bustype=EISA module=driver_name [options]Arguments
The VECTOR: line space declarations are a triple of the form:
(space_name, address_offset, size)Arguments
0x1000 (4K) bytes * slot number
and extends the full 0x1000 (4 KB) to the next slot's space. For ISA cards, the I/O space addresses are not slot dependent, but rather card jumper dependent. They can be in the range starting at byte offset 0x100 (256) and extending up to 0x400 (1024). Similarly, the ISA address space size is card dependent and limited only by the ISA address space size. The EISAMEM space can begin at offset 0xa0000 iospace1 iospace2 iospace3 | These space declarations are defined so that the driver can map to the registers and memory on the card. Typically, iospace1 is used to define the I/O register space to be referenced, and iospace2 and iospace3 are used to gain access to one or two different on-card memory spaces. |
The general form of exprobe_space allows for a more generalized extensive read/write sequence, which can be used to search for an ISA card at a particular address. The probing is accomplished by writing a value to a register located on the card and then reading it back to verify that a board responds to that location. Do not use a comparison value of 0xff because the bus floats to that value, which would cause the probe command always to believe that it had found a new board.
exprobe_space is specified as a six-tuple consisting of:
(rwseg, bus_space, address, size, value, mask)
rwseg - A sequence of one or more r's or w's indicating a read or write. To test for an EISA card, use a simple r. To test for an ISA card, use wr, which causes the value to be written then reread.
bus_space - Either EISAIO or EISAMEM. The manufacturer ID is located in EISAIO space.
address - The address offset to read. The manufacturer ID is located at 0xzC80, where z is the slot number for EISA cards. ISA cards must specify the address of a register that can be read from and written to.
size - The manufacturer ID is four bytes long, as described below. ISA cards must use the appropriate register width.
value - Compressed 4-byte value to look for (EISA). Non-0xff value for ISA.
mask - A bit mask to specify which bytes of the value to compare against.
The first two bytes (0xzC80 and 0xzC81) contain a compressed representation of the manufacturer code. The manufacturer code is a three-character code (uppercase, ASCII characters in the range of A to Z) chosen by the manufacturer and registered with the firm that distributes the EISA specification.
The manufacturer code "ISA" is used to indicate a generic ISA adapter. The three-character manufacturer code is compressed into three 5-bit values so that it can be incorporated into the two I/O bytes at 0xzC80 and 0xzC81, where z represents the slot number probed.
The compression procedure is:
ASCII for "A"-"Z" : "A" = 0x41, "Z" = 0x5a
Compressed "A" = 0x41-0x40 = 0x01 = 0000 0001
Compressed "Z" = 0x5a-0x40 = 0x1A = 0001 1010
Discard three most significant bits (they are always zero)
Compressed "A" = 0001. Compressed "Z" = 1010
"AZA" = 0 00001 11010 00001 (16-bit value)
0xzC80 = 00000111, 0xzC81h = 01000001
Figure 4-2 : Product ID Format The manufacturer ID is located at bytes offset 0xzC80-0xzC83, where z represents the slot number probed. exprobe_space usage when searching for an EISA card is:
exprobe_space = (r, EISAIO, 0xzC80, 4, mfg_id, 0xffffffff)The first argument (r) specifies that this probe consists of doing a single read. The second argument (EISAIO) declares that the address space is in the EISA register range. 0xzC80 is the offset of the manufacturer's unique ID. The size of this read is four bytes. mfg_id is the compressed 4-byte value that is returned by the particular card being searched for. The last argument is a mask which the mfg_id is ANDed against.
In addition to the system file described above, you must create a master file under /var/sysgen/master.d. (The name of the master file is the same as the name of the object file for the driver, but the master file must not have the ".o" suffix.) The FLAG field of the master file must at least include the character device flag c. (You do not need the s flag for EISA device drivers because lboot can probe for EISA devices.)
A more detailed description of the master file can be found in Chapter 2, "Writing a Device Driver," and in the master(1M) man page.
The following example explores adding an ISA card device driver to the kernel. Assuming that the driver is called isacard.o, the following steps are necessary:
The file might contain the following lines:
VECTOR: bustype=EISA module=isacard ctlr=0 adapter=0
iospace=(EISAIO,0x300,48) probe_space=(wr,EISAIO,0x300,1, 0x11,0xff)
VECTOR: bustype=EISA module=isacard ctlr=1 adapter=0
iospace=(EISAIO,0x330,48) probe_space=(wr,EISAIO,0x330,1,
0x11,0xff)
This would allow a kernel to support two of the same ISA cards located at different addresses. A one-byte test for card existence will be made at ISA I/O addresses 0x300 and 0x330. If either card returns the value written at one of those locations, the driver will be included in the kernel. Also a 48-byte ISA register address space will be allocated to the card without a memory address space being allocated in the example above.
*Flag | Prefix | Soft | #Dev | Dependencies |
c | isa | 60 | - |
Note that even though the module name is referred to as isacard, the prefix for each of the driver routines can be independently declared, in this case as simply "isa."
VECTOR: bustype=EISA module=eisacard ctlr=0 adapter=0 iospace=(EISAIO,0x1000,0x1000) iospace2=(EISAMEM,0xC8000,0x10000) exprobe_space=(r,EISAIO,0x1C80,4, 0x00008107, 0xffffffff) VECTOR: bustype=EISA module=eisacard ctlr=1 adapter=0 iospace=(EISAIO,0x2000,0x1000) iospace2=(EISAMEM,0xD8000,0x10000) exprobe_space=(r,EISAIO,0x2C80,4, 0x00008107, 0xffffffff) VECTOR: bustype=EISA module=eisacard ctlr=2 adapter=0 iospace=(EISAIO,0x3000,0x1000) iospace2=(EISMEM,0xE8000,0x10000) exprobe_space=(r,EISAIO,0x3C80,4, 0x00008107,0xffffffff) VECTOR: bustype=EISA module=eisacard ctlr=3 adapter=0 iospace=(EISAIO,0x3000,0x1000) iospace2=(EISMEM,0xF8000,0x10000) exprobe_space=(r,EISAIO,0x3C80,4, 0x00008107,0xffffffff)This will support up to four cards. In this example, the manufacturer ID is AZA with a product number and revision number of zero. In addition to specifying the I/O register space on a per-slot basis, the VECTOR: lines in the above example also reserve 0x10000 bytes of memory space for each card. Each card placed in the system will be uniquely identified to the system by its ctlr number, which also happens to correspond directly to the slot number (although this is not a requirement).